﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using INF1010_Chat;

namespace ClientChat
{
    public partial class frmClient : Form
    {
        public delegate void ClientDisconnectedDelegate();
        public ClientDisconnectedDelegate clientDisconnectedAction;
        
        public delegate void RefreshUserListDelegate();
        public RefreshUserListDelegate refreshUserListAction;

        public delegate void UserMessageReceivedDelegate();
        public UserMessageReceivedDelegate UserMessageReceivedAction;


        private bool isManagingSelection;

        private ClientChat clientChat;

        public frmClient()
        {
            InitializeComponent();
            clientChat = ClientChat.GetClientChat();
            clientDisconnectedAction = new ClientDisconnectedDelegate(ClientDisconnectedMethod);
            refreshUserListAction = new RefreshUserListDelegate(RefreshUserListMethod);
            clientChat.RefreshList += new ClientChat.ReceivedRefreshUsersEventHandler(clientChat_RefreshList);
            UserMessageReceivedAction = new UserMessageReceivedDelegate(UserMessageReceivedMethod);
            clientChat.UserMessageReceive += new ClientChat.UserMessageReceiveEventHandler(clientChat_UserMessageReceive);
            clientChat.ClientDisconnected += new ClientChat.ReceivedDisconnectNoticeEventHandler(clientChat_ClientDisconnected);
        }

        /*
         * Vide et active/désactive certains champs pour revenir à l'état déconnecté
         */
        private void ClientDisconnectedMethod()
        {
            lbUsers.Items.Clear();
            lbGroups.Items.Clear();
            EnableFields(false);
            btnConnect.Text = "Se connecter";
            txtUserName.Enabled = true;
            txtIpAdress.Enabled = true;
            nudPort.Enabled = true;
        }

        void clientChat_ClientDisconnected(object sender, EventArgs args)
        {
            if (btnConnect.InvokeRequired)
                btnConnect.Invoke(clientDisconnectedAction);
            else
                ClientDisconnectedMethod();
        }

        private void clientChat_RefreshList(object sender, EventArgs args)
        {
            if (lbUsers.InvokeRequired)
                lbUsers.Invoke(refreshUserListAction);
            else
                RefreshUserListMethod();
        }

        private void RefreshUserListMethod()
        {
            lbUsers.Items.Clear();
            foreach (User user in clientChat.Users.Where(u => !u.Name.Equals(clientChat.UserName)))
            {
                lbUsers.Items.Add(user);
            }
        }

        private void clientChat_UserMessageReceive(object sender, EventArgs args)
        {
            if (rtxtResponses.InvokeRequired)
                rtxtResponses.Invoke(UserMessageReceivedAction);
            else
                UserMessageReceivedMethod();
        }

        private void UserMessageReceivedMethod()
        {
            string newMessage = clientChat.DequeueUserMessage();

            rtxtResponses.AppendText(newMessage + Environment.NewLine);
        }


        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(txtUserName.Text))
            {
                if (!clientChat.IsConnected)
                {
                    try
                    {
                        clientChat.SendConnect(txtUserName.Text, txtIpAdress.Text, int.Parse(nudPort.Value.ToString()));
                        ClearAndEnableFields();
                        btnConnect.Text = "Se déconnecter";
                        txtUserName.Enabled = false;
                        txtIpAdress.Enabled = false;
                        nudPort.Enabled = false;
                    }
                    catch (System.Net.Sockets.SocketException sockExcep)
                    {
                        Console.WriteLine(sockExcep.StackTrace);
                        MessageBox.Show("Addresse ou port invalide.");
                    }
                }
                else
                {
                    clientChat.SendDisconnect();
                    lbUsers.Items.Clear();
                    lbGroups.Items.Clear();
                    EnableFields(false);
                    btnConnect.Text = "Se connecter";
                    txtUserName.Enabled = true;
                    txtIpAdress.Enabled = true;
                    nudPort.Enabled = true;
                    //txtUserName.ResetText();
                }
            }
        }

        private void ClearAndEnableFields()
        {
            rtxtResponses.ResetText();
            txtNewMessage.ResetText();
            txtJoinGroup.ResetText();
            EnableFields(true);
        }

        private void EnableFields(bool p)
        {
            panel1.Enabled = p;
        }

        private void btnRefreshUserList_Click(object sender, EventArgs e)
        {
            clientChat.SendRefreshUserList();
        }

        private void lbUsers_SelectedValueChanged(object sender, EventArgs e)
        {
            if (!isManagingSelection)
            {
                isManagingSelection = true;

                lbGroups.ClearSelected();

                isManagingSelection = false;
            }
        }

        private void lbGroups_SelectedValueChanged(object sender, EventArgs e)
        {
            if (!isManagingSelection)
            {
                isManagingSelection = true;

                lbUsers.ClearSelected();

                isManagingSelection = false;
            }
        }

        private void btnJoinGroup_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(txtJoinGroup.Text))
            {
                clientChat.SendJoinGroup(txtJoinGroup.Text);
                if (!lbGroups.Items.Contains(txtJoinGroup.Text))
                    lbGroups.Items.Add(txtJoinGroup.Text);
                txtJoinGroup.ResetText();
            }

        }

        private void btnQuitterGroup_Click(object sender, EventArgs e)
        {
            if (lbGroups.SelectedItem != null)
            {
                clientChat.SendLeaveGroup(lbGroups.SelectedItem.ToString());
                lbGroups.Items.Remove(lbGroups.SelectedItem);
            }
            //Todo rafraichir liste de groupes
        }

        /*
         * Utiliser lors du click sur l'envoi de message 
         */
        private void SendMessage()
        {
            string messageSent;
            if (lbGroups.SelectedItems.Count > 0)
                messageSent = clientChat.SendMessageToGroup(lbGroups.SelectedItem.ToString(), txtNewMessage.Text);
            else if (lbUsers.SelectedItems.Count > 0)
                messageSent = clientChat.SendMessageToUser(lbUsers.SelectedItem.ToString(), txtNewMessage.Text);
            else
                messageSent = clientChat.SendMessageToAll(txtNewMessage.Text);

            txtNewMessage.ResetText();
            rtxtResponses.AppendText(messageSent + Environment.NewLine);
        }

        private void btnSendMessage_Click(object sender, EventArgs e)
        {
            SendMessage();
        }

        private void frmClient_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (clientChat.IsConnected)
                clientChat.SendDisconnect();
        }

        private void btnAll_Click(object sender, EventArgs e)
        {
            lbGroups.ClearSelected();
            lbUsers.ClearSelected();
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Enter && clientChat.IsConnected && txtNewMessage.Focused)
            {
                SendMessage();
                return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        

    }
}
